﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace AssemblerCompiler
{
    public partial class NumberedTextBoxUC : UserControl
    {
        public NumberedTextBoxUC()
        {
            this.InitializeComponent();

            //this.richTextBox1.Font = new Font("Microsoft Sans Serif", 8.25f);

            //numberLabel.Font = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size - 1.019f);
            this.numberLabel.Font = new Font(this.richTextBox1.Font.FontFamily, this.richTextBox1.Font.Size);

            this.richTextBox1.Enter += this.OnEnter;
            this.richTextBox1.Leave += this.OnLeave;
            this.richTextBox1.SelectionChanged += this.OnSelectionChanged;
        }

        private void updateNumberLabel()
        {
            //we get index of first visible char and number of first visible line
            var pos = new Point(0, 0);
            int firstIndex = this.richTextBox1.GetCharIndexFromPosition(pos);
            int firstLine = this.richTextBox1.GetLineFromCharIndex(firstIndex);

            //now we get index of last visible char and number of last visible line
            pos.X = this.ClientRectangle.Width;
            pos.Y = this.ClientRectangle.Height;
            int lastIndex = this.richTextBox1.GetCharIndexFromPosition(pos) + 1;
            int lastLine = this.richTextBox1.GetLineFromCharIndex(lastIndex);

            //this is point position of last visible char, we'll use its Y value for calculating numberLabel size
            pos = this.richTextBox1.GetPositionFromCharIndex(lastIndex);

            //finally, renumber label
            this.numberLabel.Text = "";
            for (int i = firstLine; i <= lastLine + 1; i++)
            {
                this.numberLabel.Text += i + 1 + "\n";
            }
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            this.updateNumberLabel();

            if (this.TextChanged != null)
            {
                this.TextChanged(sender, e);
            }
        }

        private void richTextBox1_VScroll(object sender, EventArgs e)
        {
            //move location of numberLabel for amount of pixels caused by scrollbar
            int d = this.richTextBox1.GetPositionFromCharIndex(0).Y % (this.richTextBox1.Font.Height + 1);
            this.numberLabel.Location = new Point(0, d);

            this.updateNumberLabel();
        }

        private void richTextBox1_Resize(object sender, EventArgs e)
        {
            this.richTextBox1_VScroll(null, null);
        }

        private void richTextBox1_FontChanged(object sender, EventArgs e)
        {
            this.updateNumberLabel();
            this.richTextBox1_VScroll(null, null);
        }

        public void OnTextChanged()
        {
            if (this.TextChanged != null)
            {
                this.TextChanged(this.richTextBox1, null);
            }
        }

        #region RichTextBox events, properties and functions

        public string[] Lines
        {
            get
            {
                return this.richTextBox1.Lines;
            }

            set
            {
                this.richTextBox1.Lines = value;
            }
        }

        public new string Text
        {
            get
            {
                return this.richTextBox1.Text;
            }

            set
            {
                this.richTextBox1.Text = value;
            }
        }

        public int SelectionStart
        {
            get
            {
                return this.richTextBox1.SelectionStart;
            }

            set
            {
                this.richTextBox1.SelectionStart = value;
            }
        }

        public int SelectionLength
        {
            get
            {
                return this.richTextBox1.SelectionLength;
            }

            set
            {
                this.richTextBox1.SelectionLength = value;
            }
        }

        public Font SelectionFont
        {
            get
            {
                return this.richTextBox1.SelectionFont;
            }

            set
            {
                this.richTextBox1.SelectionFont = value;
            }
        }

        public Color SelectionColor
        {
            get
            {
                return this.richTextBox1.SelectionColor;
            }

            set
            {
                this.richTextBox1.SelectionColor = value;
            }
        }

        public new event EventHandler TextChanged;

        public new event EventHandler Enter;

        public new event EventHandler Leave;

        public event EventHandler SelectionChanged;

        private void OnEnter(object sender, EventArgs e)
        {
            if (this.Enter != null)
            {
                this.Enter(sender, e);
            }
        }

        private void OnLeave(object sender, EventArgs e)
        {
            if (this.Leave != null)
            {
                this.Leave(sender, e);
            }
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            if (this.SelectionChanged != null)
            {
                this.SelectionChanged(sender, e);
            }
        }

        public int GetFirstCharIndexFromLine(int index)
        {
            return this.richTextBox1.GetFirstCharIndexFromLine(index);
        }

        public int GetLineFromCharIndex(int index)
        {
            return this.richTextBox1.GetLineFromCharIndex(index);
        }

        public void Select(int start, int length)
        {
            this.richTextBox1.Select(start, length);
        }

        public void ScrollToCaret()
        {
            this.richTextBox1.ScrollToCaret();
        }

        #endregion
    }
}